#ifndef UTILS_H 
#define UTILS_H
 
#include "array.h"
#include "dynamic_array.h"
#include "resizable_array.h"

struct Utils{
    template<class T>
    static void move(Array<T>& dst, const int dstStart, const T src[], const int count);

    template<class T>
    static void move(Array<T>& dst, const int dstStart, 
                     const Array<T>& src, const int srcStart, const int count);

    template<class T>
    static void move(Array<T>& dst, const Array<T>& src);

    template<class T>
    static void merge(Array<T>& dst, const Array<T>& src1, const Array<T>& src2);

    template<class T>
    static DynamicArray<T> merge(const Array<T>& src1, const Array<T>& src2);

    template<class T>
    static void Utils::fill(Array<T>& arr, const int start, const T& o, const int count);

    template<class T>
    static void Utils::zeroize(Array<T>& arr);
};

#include <exception>
#include <typeinfo>

template<class T>
void Utils::move(Array<T>& dst, const int dstStart, const T src[], const int count){
    dst.move(dstStart, src, count);
}

template<class T>
void Utils::move(Array<T>& dst, const int dstStart, const Array<T>& src, const int srcStart, const int count){
    src.valid(srcStart, count);
    dst.move(dstStart, &src[0]+srcStart, count);
}

template<class T>
void Utils::move(Array<T>& dst, const Array<T>& src){
    dst.move(0, src, 0, src.size());
}

template<class T>
void Utils::merge(Array<T>& dst, const Array<T>& src1, const Array<T>& src2){
    DynamicArray<T> _src1(src1);
    DynamicArray<T> _src2(src2);
    const int reqSize = _src1.size() + _src2.size();
    try{
        ResizableArray<T>& _dst = dynamic_cast<ResizableArray<T>&>(dst);
        _dst.resize(reqSize);
    }catch (const std::bad_cast&){
    }
    dst.valid(0, reqSize);
    move(dst, _src1);
    move(dst, _src1.size(), _src2, 0, _src2.size());
}

template<class T>
DynamicArray<T> Utils::merge(const Array<T>& src1, const Array<T>& src2){
    DynamicArray<T> dst(src1.size() + src2.size());
    merge(dst, src1, src2);
    return dst;
}


template<class T>
void Utils::fill(Array<T>& arr, const int start, const T& o, const int count){
    arr.fill(start, o, count);
}

template<class T>
void Utils::zeroize(Array<T>& arr){
    const T o = T();
    arr.fill(0, o, arr.size());
}


#endif /*#define UTILS_H*/
